package com.lik888.web1.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lik888.web1.Log.Log;
import com.lik888.web1.config.JwtProperties;
import com.lik888.web1.constants.UserContext;
import com.lik888.web1.entity.DTO.UserTableDTO;
import com.lik888.web1.entity.R;
import com.lik888.web1.entity.UserLogin;
import com.lik888.web1.entity.UserTable;
import com.lik888.web1.entity.UserproducionConnectiontable;
import com.lik888.web1.mapper.UserProductiontableMapper;
import com.lik888.web1.mapper.UserTableMapper;
import com.lik888.web1.mapper.UserproducionConnectiontableMapper;
import com.lik888.web1.service.IUserTableService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lik888.web1.utils.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2025-10-30
 */
@Service
@RequiredArgsConstructor
public class UserTableServiceImpl extends ServiceImpl<UserTableMapper, UserTable> implements IUserTableService {
    private final JwtTool jwtTool;
    private final JwtProperties jwtProperties;
    private final StringRedisTemplate stringRedisTemplate;
    private final UserDetailsService userDetailsService;
    private final AuthenticationManager authenticationManager;
    private final UserProductiontableMapper userProductiontableMapper;
    private final PasswordEncoder passwordEncoder;
    private final UserproducionConnectiontableMapper userproducionConnectiontableMapper;
    private final UserTableMapper userTableMapper;
    private final JavaMailSender mailSender;


    @Override
    @Transactional
    @Log(value = "用户登录")
    public String Login(String username, String password) {
        //封装Authentication对象
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(username,password);
        // 3.调用authenticationManager.authenticate()方法进行认证
        Authentication authenticate = authenticationManager.authenticate(authentication);
        if (authenticate == null) {throw new RuntimeException("登录异常");}
                System.out.println(authenticate);
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        UserLogin loginuser = (UserLogin) authenticate.getPrincipal();
        // 4. 将对象序列化为Json字符串并返回，
        Long userid = loginuser.getUser().getUserId();
        String token = jwtTool.createToken(userid.longValue(), jwtProperties.getTokenTTL());
        stringRedisTemplate.opsForValue().set("KingyoungMALL:user:"+userid,token,30, TimeUnit.MINUTES);
        System.out.println(token);
        return token;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    //后续做并发控制
    public Boolean Register(UserTable userTable) {
        //判断id是否存在
        String username = userTable.getUsername();
        if (StringUtils.isEmpty(username)) {
            throw new RuntimeException("用户名不能为空");
        }
        //判断密码是否存在
        String password = userTable.getPassword();
        if (StringUtils.isEmpty(password)) {
            throw new RuntimeException("密码不能为空");
        }

        //判断用户名是否存在
        UserTable userTable4 = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUsername, username));
        if (userTable4 != null) {
            throw new RuntimeException("用户名已存在");
        }
        //判断appId是否存在
        Long appId = userTable.getAppId();
        if (appId != null) {
            //查询appId是否存在
            UserTable userProductiontable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getAppId, appId));
            if (!BeanUtil.isEmpty(userProductiontable)) {
                throw new RuntimeException("此appId已绑定用户");
            }
        }
        //生成创新时间
        userTable.setCreateTime(LocalDateTime.now());
        userTable.setUpdateTime(LocalDateTime.now());
//TODO 后续会改为nums类型
        //判断是否使用第三方登录
        if (userTable.getUserApp() == null) {
            userTable.setUserApp(2);
        }
        //搜索连接表是否为空
        String encode = passwordEncoder.encode(password);
        userTable.setPassword(encode);
        //插入用户表
        userTable.setUserImg("https://java-ai-web-lik.oss-cn-chengdu.aliyuncs.com/091d6450-cc06-4f31-b100-a0d633f47119.JPG");
        userTable.setUserInfo("这个人很懒什么都没有留下OvO");
        userTable.setUserNickname("樾阳" + RandomUtil.randomNumbers(6) + RandomUtil.randomString(4));
        userTableMapper.insert(userTable);

        //TODO
        //从用户表中拿取id
        UserTable userTable1 = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUsername, username));
        if (userTable1 == null) {
            throw new RuntimeException("用户名不存在");
        }
        UserproducionConnectiontable userproducionConnectiontable = userproducionConnectiontableMapper.selectOne(new LambdaQueryWrapper<UserproducionConnectiontable>().eq(UserproducionConnectiontable::getUserId, userTable1.getUserId()));
        if (userproducionConnectiontable != null) {
            return true;
        }

        //创建实例化对象
        UserproducionConnectiontable connectionTable = new UserproducionConnectiontable();
        //如果为空
       connectionTable.setUserId(userTable1.getUserId());
        //默认权限列表为1
        connectionTable.setProductionId(1);
        userproducionConnectiontableMapper.insert(connectionTable);
        return true;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean CheckPhone() {
        Long userid = UserContext.getUser();
        if (userid == null) {
            throw new RuntimeException("用户未登录");
        }
        //判断是否有手机号
        UserTable userTable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUserId, userid));
        if (userTable == null) {
            throw new RuntimeException("用户不存在");
        }
        if (StringUtils.isEmpty(userTable.getPhone())) {
            return false;
        }
        if (StringUtils.isEmpty(userTable.getEmail())) {
            return false;
        }
        return true;
    }


    //email 和 手机号 不能为空 任一为空 则需要全部重新补全

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R DoubleRegister(String phone, String email) {
        Long userid = UserContext.getUser();
        if (userid == null) {
            throw new RuntimeException("用户未登录,可能存在恶意登录");
        }
        //判断是否有手机号
        UserTable userTable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUserId, userid));
        if (userTable == null) {
            throw new RuntimeException("用户不存在");
        }

        //查询全部数据库是否存在手机号或邮箱
        UserTable userTable1 = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getPhone, phone));
        if (userTable1 != null) {
            throw new RuntimeException("手机号已存在");
        }
        UserTable userTable2 = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getEmail, email));
        if (userTable2 != null) {
            throw new RuntimeException("邮箱已存在");
        }
        if (StringUtils.isEmpty(phone)) {
            throw new RuntimeException("手机号不能为空");
        }
        if (StringUtils.isEmpty(email)) {
            throw new RuntimeException("邮箱不能为空");
        }
        userTable.setPhone(phone);
        userTable.setEmail(email);
        userTableMapper.updateById(userTable);
        return R.ok("已成功绑定手机号和邮箱");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R GetUserMessage() {
        Long userid = UserContext.getUser();
        if (userid == null) {
            throw new RuntimeException("用户未登录");
        }
        UserTable userTable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUserId, userid));
        if (userTable == null) {
            throw new RuntimeException("用户不存在");
        }
        return R.ok(userTable);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R ForgetCheck(String email, String username) {
//1.Check 用户名是否存在 email是否存在
        UserTable userTableusername = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUsername, username));
        if (userTableusername == null) {
            throw new RuntimeException("用户名不存在,请不要恶意查询,若持续出现异常,请联系管理员");
        }
         UserTable  userTableemail = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getEmail, email));
        if (userTableemail == null) {
            throw new RuntimeException("邮箱不存在,请不要恶意查询,若持续出现异常,请联系管理员");
        }

        String email1 = userTableemail.getEmail();
        String email2 = userTableusername.getEmail();
        String username1 = userTableemail.getUsername();
        String username2 = userTableusername.getUsername();
        if (!email1.equals(email2)) {
                throw new RuntimeException("用户名和邮箱不匹配");
        }
        if (!username1.equals(username2)) {
                throw new RuntimeException("用户名和邮箱不匹配");
        }

        String s = stringRedisTemplate.opsForValue().get("forgetkey:" + username);
        if (s != null && !s.trim().isEmpty()){
            return R.error("当前验证码有效,请稍后再发送验证码！");
        }
        //2.向邮箱发送验证码（集成邮件功能）
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("542046350@qq.com");//发送的qq邮箱
        message.setTo(email);//接收邮件的qq邮箱
        message.setSubject("主题：注册验证码");
        //随机生成6位数字验证码
        Random random = new Random();
        int randomNum = random.nextInt(1000000);
        String randomCode = String.format("%06d", randomNum);
        System.out.println(randomNum);
        String text = "您忘记密码操作的验证码为："+randomCode;
        message.setText(text);
        mailSender.send(message);//发送邮件
        stringRedisTemplate.opsForValue().set("forgetkey:"+username,randomCode,5,TimeUnit.MINUTES);
        return R.ok("验证码已发送到您的邮箱,请输入验证码,有效期为5分钟");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserTable ChangeSelf(UserTableDTO userTableDTO) {
        Long userid = UserContext.getUser();
        if (userid == null) {
            throw new RuntimeException("用户未登录");
        }
        UserTable userTable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUserId, userid));
        if (userTable == null) {
            throw new RuntimeException("用户不存在");
        }
        userTable.setUserImg(userTableDTO.getUserImg());
        userTable.setUserInfo(userTableDTO.getUserInfo());
        userTable.setUserNickname(userTableDTO.getUserNickname());
        userTable.setUpdateTime(userTableDTO.getUpdateTime());
        userTableMapper.updateById(userTable);
        return userTable;
    }

    @Override
    public Boolean CheckIdCard() {
        //查看用户是否绑定身份证号
        Long userid = UserContext.getUser();
        if (userid == null) {
            throw new RuntimeException("用户未登录");
        }
        UserTable userTable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUserId, userid));
        if (userTable == null) {
            throw new RuntimeException("用户不存在");
        }
        if (StringUtils.isEmpty(userTable.getUId())) {
           return false;
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserTable CheckIdCardForBuyOrSell(String idcard,Boolean isTrue) {
        //判断isTrue是否为false 不是false 则为异常攻击请求
        if (isTrue) {
            throw new RuntimeException("请不要恶意攻击，不然将被拉入黑名单！");
        }


        //审核身份证号是否存在
        if (StringUtils.isEmpty(idcard)) {
            throw new RuntimeException("身份证号不能为空");
        }
        //审核身份证号是否符合规则
        //身份证号正则表达式
        String idcardRegex = "^[1-9]\\d{5}(?:18|19|20)\\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\\d|30|31)\\d{3}[\\dXx]$";
        if (!idcard.matches(idcardRegex)) {
            throw new RuntimeException("身份证号格式错误");
        }
        //判断身份证号是否已绑定
        UserTable userTableidcard = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUId, idcard));
        if (userTableidcard != null) {
            throw new RuntimeException("身份证号已绑定");
        }
        //Context中获取用户ID
        Long userid = UserContext.getUser();
        if (userid == null) {
            throw new RuntimeException("用户未登录");
        }
        UserTable userTable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUserId, userid));
        if (userTable == null) {
            throw new RuntimeException("用户不存在");
        }
        //将idcard插入到UserTable中
        userTable.setUId(idcard);
        userTableMapper.updateById(userTable);
        return userTable;
    }

    @Override
    public Boolean ReturnCode( String username,String code) {
        String redisCode = stringRedisTemplate.opsForValue().get("forgetkey:"+username);
        if (StringUtils.isEmpty(redisCode)) {
            throw new RuntimeException("验证码过期，请重新获取");
        }
        if (!redisCode.equals(code)) {
            throw new RuntimeException("验证码错误");
        }
        return true;
    }

    @Override
    public R<UserTable> ResetPassword(String username, String password, Boolean isTrue) {
        //判断isTure是否为true 不然标记为异常
        if (!isTrue) {
            throw new RuntimeException("修改密码无效，请重新操作");
        }
        //根据用户名查询用户
        UserTable userTable = userTableMapper.selectOne(new LambdaQueryWrapper<UserTable>().eq(UserTable::getUsername, username));
        if (userTable == null) {
            throw new RuntimeException("用户不存在");
        }
        //将密码加密后更新到数据库
        userTable.setPassword(passwordEncoder.encode(password));
        userTableMapper.updateById(userTable);
        String A = "密码重置成功！" +"账户名为:"+username +"\n"+"新密码为:"+password+"\n"+"请妥善保管新密码，避免泄露！";
        return R.ok(userTable,A);
    }


//    @Override
//    public R Login(User user) {
//        /*2.封装Authentication对象*/
//        UsernamePasswordAuthenticationToken authentication =
//                new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
//        /*3.调用authentication()方法进行认证*/
//        Authentication authenticate = authenticationManager.authenticate(authentication);
//
//        if (authenticate == null) {throw new RuntimeException("登录异常");}
//        System.out.println(authenticate);
//        SecurityContextHolder.getContext().setAuthentication(authenticate);
//        UserLogin loginuser = (UserLogin) authenticate.getPrincipal();
//
//        // 4. 将对象序列化为Json字符串并返回，
//        Integer userid = loginuser.getUser().getUserid();
//        String token = jwtTool.createToken(userid.longValue(), jwtProperties.getTokenTTL());
//
//        stringRedisTemplate.opsForValue().set("securitydemo:user:"+userid,token,30, TimeUnit.MINUTES);
//
//        return token;
//    }


}
